/*******************************************************************************
 ** 
 ** This file is part of cmemtrac
 ** (C) 2011 Kevin Druelle 
 **
 ** Cmemtrac is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 ** 
 ** Cmemtrac is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 ** 
 ** You should have received a copy of the GNU General Public License
 ** along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 ** 
 ******************************************************************************/

#include <cstack.h>

typedef struct cstack_elem_st             *Stack_elem_t;

#define STACK_MAGIC_NUMBER 0xA7B9C3D1

struct cstack_elem_st{
	void 						* pData;
	Stack_elem_t                                    next;
};

struct cstack_st{
	size_t                                          size;
	Stack_elem_t                            	first;
	unsigned long					magic;
};

static int cstack_isValid(cstack_t * stack){
	if(stack == NULL || *stack == NULL)
		return 0;
	if((*stack)->magic != STACK_MAGIC_NUMBER)
		return 0;
	return 1;
}

int cstack_init(cstack_t * stack){
	(*stack) = (cstack_t)malloc(sizeof(struct cstack_st));
	(*stack)->size = 0;
	(*stack)->first = NULL;
	(*stack)->magic = STACK_MAGIC_NUMBER;
	return 0;
}

int cstack_isEmpty(cstack_t * stack){
	if(!cstack_isValid(stack))
		return -1;
	return (((*stack)->size == 0) ? 1 : 0);
}

size_t cstack_getSize(cstack_t * stack){
	if(!cstack_isValid(stack))
		return 0;
	return (*stack)->size;
}

void * cstack_top(cstack_t * stack){
	if(!cstack_isValid(stack) || cstack_isEmpty(stack) )
		return NULL;
		
	return (*stack)->first->pData;
}

int cstack_push(cstack_t * stack, void * pData){
	Stack_elem_t elem;
	if(!cstack_isValid(stack))
		return -1;
		
	elem = (Stack_elem_t)malloc(sizeof(struct cstack_elem_st));
	elem->pData = pData;
	if((*stack)->size == 0){
		elem->next = NULL;
	}else{
		elem->next = (*stack)->first;
	}
	(*stack)->first = elem;
	(*stack)->size++;
	return 0;
}

void * cstack_pop(cstack_t * stack){
	Stack_elem_t elem = NULL;
	void * pData = NULL;
	
	if(!cstack_isValid(stack) || cstack_isEmpty(stack) )
		return NULL;
		
	elem = (*stack)->first;
	(*stack)->first = elem->next;
	(*stack)->size--;
	pData = elem->pData;
	free(elem);
	return pData;
}

void cstack_delete(cstack_t * stack){
	while(cstack_pop(stack));
	free(*stack);
}





